﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using CloudClip.Clip;
using CloudClip.HelperMehtod;
using CloudClip.LocalFile;
using CloudClip.Properties;
using ExtensionLibrary.Exception;

namespace CloudClip
{
    public partial class frmMain : Form
    {
        public const string AppName = "CloudClip 1.0.5";
        private frmMenu _frmMenu = null;
        private frmSetting _frmSetting = null;

        private bool IsStartClip = false;
        private IntPtr _ClipboardViewerNext;
        private string _sTempChange;
        private NotifyIcon notifyIcon1;
        private ContextMenuStrip _ContextMenuStrip;
        private HotKey _hotKey = null;
        private IntPtr _foregroundWindow;
        public IClipProvider ClipProvider;
        public Setting Setting;
        
        public frmMain()
        {
            InitializeComponent();

            #region Init_icon
            this.notifyIcon1 = new NotifyIcon(this.components);
            this.notifyIcon1.Icon = Resources.Icon;
            this.notifyIcon1.Text = AppName;
            this.notifyIcon1.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.notifyIcon1_MouseDoubleClick);
            this.notifyIcon1.MouseDown += new MouseEventHandler(notifyIcon1_MouseDown);
            #endregion

            Init();
        }

        public void Init() 
        {
            try
            {
                //視窗初始化
                if (_frmSetting == null)
                    _frmSetting = new frmSetting(this);
                if (_frmMenu == null)
                    _frmMenu = new frmMenu();

                if (SettingHelper.CheckSetting() == false)
                {
                    throw new ValidationException("請先設定一些必要參數!");
                }else
                {
                    //讀取設定檔
                    Setting = SettingHelper.Load();
                }

                //都先載入LocalFile
                ClipProvider = new LocalFileClipProvider(Setting);
                ClipProvider.SyncClipList();            
            
                #region Init_HotKey
                //註冊組合鍵事件
                if (_hotKey != null)
                    _hotKey.Dispose();

                _hotKey = new HotKey(this.Handle, (Keys)Setting.HotKey3, (Keys)Setting.HotKey1, (Keys)Setting.HotKey2);
                _hotKey.OnHotkey += new HotKey.HotkeyEventHandler(hotkey1_OnHotkey);
                #endregion
            }
            catch (Exception ex)
            {
                if (ex is ValidationException)
                {
                    MessageBox.Show(((ValidationException)ex).ValidationMessage);
                    return;
                }
                throw;
            }
        }
        
        #region ContextMenu

        private ContextMenuStrip GetNotifyIconContextMenuStrip()
        {
            if (_ContextMenuStrip == null)
            {
                _ContextMenuStrip = new ContextMenuStrip();
                _ContextMenuStrip.ItemClicked += new ToolStripItemClickedEventHandler(NotifyIconContextMenuStrip_ItemClicked);
            }

            _ContextMenuStrip.Items.Clear();
            _ContextMenuStrip.ShowItemToolTips = false;

            List<ClipRow> clipList = ClipProvider.GetClipList();
            if (clipList == null)
                return _ContextMenuStrip;

            int i = 1;
            foreach (ClipRow clipRow in clipList)
            {
                ToolStripItem item = new ToolStripMenuItem();
                string sPrefix = string.Empty;
                string sText = clipRow.ClipUnit.ToIntroduction();

                if (i<10)//幫小於10的 加上鍵盤快速鍵
                    sPrefix = "&";

                item.Text = string.Format("({0}{1}) {2}", sPrefix, i, sText.Replace(Environment.NewLine, " "));
                item.ToolTipText = clipRow.ClipUnit.ToText();
                item.TextAlign = ContentAlignment.MiddleLeft;
                _ContextMenuStrip.Items.Add(item);
                i++;
            }
            _ContextMenuStrip.Items.Add(new ToolStripSeparator());
            _ContextMenuStrip.Focus();
            return _ContextMenuStrip;
        }

        private void NotifyIconContextMenuStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            ToolStripItem item = e.ClickedItem;
            switch (item.Text)
            {
                case "取消":
                    ((ContextMenuStrip)sender).Hide();
                    return;
                case "設定":
                    ShowSettingForm();
                    return;
                case "關閉":
                    Application.Exit();
                    return;
                case "同步":
                    this.SyncClipList();
                    return;
            }

            if (item.ToolTipText == null)
                return;

            List<ClipRow> clipList = ClipProvider.GetClipList();
            ClipRow clipRow = clipList.AsParallel().Where(s => s.ClipUnit.ToText() == item.ToolTipText).FirstOrDefault();
            if (clipRow != null)
            {
                //根據不同物件塞進剪貼簿
                clipRow.ClipUnit.SetClipboard();
                
                //找回之前的視窗
                User32.SetForegroundWindow(_foregroundWindow);
                
                //是否按下貼上
                if (Setting.IsAutoPast)
                    SendKeys.Send("^v");
            }
        }
       
        #endregion

        #region Keyboard & hotkey & MouseEvent

        private void notifyIcon1_MouseDown(object sender, MouseEventArgs e)
        {
            this.notifyIcon1.ContextMenuStrip = GetNotifyIconContextMenuStrip();
            this.notifyIcon1.ContextMenuStrip.Items.Add("同步");
            this.notifyIcon1.ContextMenuStrip.Items.Add("設定");
            this.notifyIcon1.ContextMenuStrip.Items.Add("關閉");

        }

        private void KeyboardHook_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Escape)
            {
                _frmMenu.ContextMenuStrip.Hide();
            }

            if (e.KeyData == Keys.Up || e.KeyData == Keys.Down)
            {
                if (_frmMenu.ContextMenuStrip.Focused == false)
                {
                    _frmMenu.ContextMenuStrip.Focus();
                }
            }
        }
        
        private void hotkey1_OnHotkey(object sender, HotKeyEventArgs e)
        {
            _foregroundWindow = User32.GetForegroundWindow();

            if (ClipProvider == null)
                return;
            _frmMenu.Show();
            _frmMenu.Activate();
            _frmMenu.ContextMenuStrip = GetNotifyIconContextMenuStrip();
            _frmMenu.ContextMenuStrip.Items.Add("取消");
            _frmMenu.ContextMenuStrip.Show(Cursor.Position.X, Cursor.Position.Y);
            _frmMenu.ContextMenuStrip.Focus();
            _frmMenu.Hide();
        }

        #endregion
      
        private void frmMain_SizeChanged(object sender, EventArgs e)
	    {
	        if (this.WindowState == FormWindowState.Minimized)
	        {
	            HideSettingForm();
	        }
	    }

        protected void notifyIcon1_MouseDoubleClick(object sender, EventArgs e)
        {
            ShowSettingForm();
        }

        private void frmMain_Load(object sender, System.EventArgs e)
        {
            IsStartClip = true;
            this.notifyIcon1.Visible = true;
            this.Hide();

            if (Setting == null)
                ShowSettingForm();

            //註冊剪貼簿事件
            RegisterClipboardViewer(this.Handle);
            //監聽全域鍵盤事件
            KeyboardHook.GlobalKeyDown += KeyboardHook_KeyDown;
        }

        private void HideSettingForm()
        {
            if (_frmSetting != null)
                _frmSetting.Hide();
        }

        private void ShowSettingForm()
        {
            if (_frmSetting != null)
            {
                //讓Form再度顯示，並寫狀態設為Normal
                _frmSetting.Show();
                _frmSetting.WindowState = FormWindowState.Normal;
                _frmSetting.Activate();
            }
        }
        
        /// <summary>
        /// Register this form as a Clipboard Viewer application
        /// </summary>
        private void RegisterClipboardViewer(IntPtr intPtr)
        {
            _ClipboardViewerNext = User32.SetClipboardViewer(intPtr);
        }
        
        /// <summary>
        /// Remove this form from the Clipboard Viewer list
        /// </summary>
        private void UnregisterClipboardViewer(IntPtr intPtr)
        {
            User32.ChangeClipboardChain(intPtr, _ClipboardViewerNext);
        }

        protected override void WndProc(ref Message m)
        {
            switch ((Msgs)m.Msg)
            {
                case Msgs.WM_DRAWCLIPBOARD:
                    OnClipboardChanged();
                    User32.SendMessage(_ClipboardViewerNext, m.Msg, m.WParam, m.LParam);
                    break;

                case Msgs.WM_CHANGECBCHAIN:
                    if (m.WParam == _ClipboardViewerNext)
                    {
                        _ClipboardViewerNext = m.LParam;
                    }
                    else
                    {
                        User32.SendMessage(_ClipboardViewerNext, m.Msg, m.WParam, m.LParam);
                    }
                    break;

                default:
                    base.WndProc(ref m);
                    break;
            }
        }
        
        private void OnClipboardChanged()
        {
            if (IsStartClip == false)
                return;

            if(ClipProvider == null || ClipProvider.CheckWorking() == false)
                return;

            IClipUnit clipUnit;
            if (Clipboard.ContainsText())
            {
                clipUnit = new TextClipUnit(Clipboard.GetText());
            }
            else
            {
                //不支援的格式就不做了
                return;
            }

            if (clipUnit.ToText() == _sTempChange || clipUnit == null)
                return;

            try
            {
                if (backgroundWorker1.IsBusy == false)
                    backgroundWorker1.RunWorkerAsync(clipUnit);
            }
            catch
            {
            }
            finally
            {
                _sTempChange = clipUnit.ToText();
            }
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            IClipUnit clipUnit = e.Argument as IClipUnit;
            ClipProvider.SetClipData(clipUnit);
        }

        private void SyncClipList()
        {
            if (ClipProvider == null)
                return;

            ClipProvider.SyncClipList();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
           this.SyncClipList();
        }
    }

  


}
